home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / graphics / qrt.lzh / RAY.C < prev    next >
C/C++ Source or Header  |  1989-02-16  |  19KB  |  771 lines

  1. /************************************************************
  2.  
  3.                      ray trace module
  4.  
  5.  ************************************************************/
  6.  
  7. #include <math.h>
  8. #include "qrt.h"
  9.  
  10. /* #define RAYDEBUG 1 */
  11.  
  12. OBJ_PTR new_line(), new_obj();
  13.  
  14.  
  15. /**********************************************************
  16.  
  17.   Diffuse color module. Also compute specular reflections
  18.   here for efficiency sake - only one lamp eneumerator
  19.   needed that way.
  20.  
  21.  **********************************************************/
  22.  
  23. DiffColor(color,cinfo,norm,loc,oline)
  24.   SVECT_PTR color;
  25.   VECT_PTR norm,loc;
  26.   CINFO_PTR cinfo;
  27.   OBJ_PTR oline;
  28. {
  29.   OBJ_PTR lamp, line, CurrObj, Ray_Hit();
  30.   float t;
  31.   register float dist, t1,t2;
  32.   VECTOR refl, atten;
  33.  
  34.   line=new_line();
  35.   VectEQ(&(line->loc),loc);
  36.   lamp=THEWORLD.lamps;
  37.  
  38.   while (lamp!=NULL) {
  39.  
  40. #   ifdef ROBUST
  41.       if (lamp->type!=LAMP) Error(INTERNAL_ERROR,601);
  42. #   endif
  43.  
  44.     /* find dir to lamp */
  45.     VecSubtract(&(line->vect1),&(lamp->loc),loc);
  46.  
  47.     CurrObj=NULL;
  48.     atten.x = atten.y = atten.z = 1.00;
  49.  
  50.     if (def.shadow==TRUE) {
  51.  
  52.       /* set light attenuation factor */
  53.  
  54.       CurrObj=Ray_Hit(THEWORLD.stack,line,&t,TRUE,TRUE,&atten);
  55.  
  56.       THEWORLD.to_lamp++;
  57.     }
  58.  
  59.     if (CurrObj==NULL) {                         /* hit nothing ? */
  60.  
  61.       dist = DotProd((line->vect1),(line->vect1));
  62.       Normalize(&(line->vect1));
  63.  
  64.       if (cinfo->diff.r>0 || cinfo->diff.g>0 || cinfo->diff.b>0) {
  65.         t1 = DotProd((*norm),(line->vect1));
  66.  
  67.         if (t1>0) {
  68.           t2 = lamp->vect1.y*t1/sqrt(dist);
  69.  
  70.           color->r+=(short)((lamp->cinfo.amb.r) * atten.x *
  71.                     t2*(cinfo->diff.r)/CNUM);
  72.           color->g+=(short)((lamp->cinfo.amb.g) * atten.y *
  73.                     t2*(cinfo->diff.g)/CNUM);
  74.           color->b+=(short)((lamp->cinfo.amb.b) * atten.z *
  75.                     t2*(cinfo->diff.b)/CNUM);
  76.         }
  77.       }
  78.  
  79.       if (cinfo->sreflect>0) {                 /* specular */
  80.         line->vect1.x = -line->vect1.x;        /* reverse line */
  81.         line->vect1.y = -line->vect1.y;
  82.         line->vect1.z = -line->vect1.z;
  83.         Reflect(&refl,&(line->vect1),norm);
  84.         t1 = -DotProd(refl,(oline->vect1));
  85.         if (t1>0) {
  86.  
  87.           t2 = pow(t1,cinfo->sreflect)*        /* this is slow !! */
  88.                lamp->vect1.y/sqrt(dist);
  89.  
  90.           t2 *= (float)cinfo->reflect/(float)CNUM;
  91.  
  92.           color->r+=(short)(t2 * atten.x * (lamp->cinfo.amb.r));
  93.           color->g+=(short)(t2 * atten.y * (lamp->cinfo.amb.g));
  94.           color->b+=(short)(t2 * atten.z * (lamp->cinfo.amb.b));
  95.         }
  96.       }
  97.     }
  98.     lamp=lamp->nextobj;
  99.   }
  100.  
  101. # ifdef RAYDEBUG
  102.     printf("DIFFCOLOR: r=%d, g=%d, b=%d\n",
  103.             color->r, color->g, color->b);
  104. # endif
  105.  
  106.   free(line);
  107. }
  108.  
  109.  
  110. /**********************************************************
  111.  
  112.                      Ambient color module
  113.  
  114.    Really simple - just add the color, no questions asked.
  115.  
  116.  **********************************************************/
  117.  
  118. AmbColor(color, cinfo, norm, loc)
  119.   SVECT_PTR color;
  120.   VECT_PTR norm, loc;
  121.   CINFO_PTR cinfo;
  122. {
  123.   color->r+=(short)((int)cinfo->amb.r*(int)cinfo->diff.r/CNUM);
  124.   color->g+=(short)((int)cinfo->amb.g*(int)cinfo->diff.g/CNUM);
  125.   color->b+=(short)((int)cinfo->amb.b*(int)cinfo->diff.b/CNUM);
  126.  
  127. # ifdef RAYDEBUG
  128.     printf("AMBCOLOR: added r=%d, g=%d, b=%d\n",
  129.             cinfo->amb.r,cinfo->amb.g,cinfo->amb.b);
  130. # endif
  131. }
  132.  
  133.  
  134. /**********************************************************
  135.  
  136.                  Transmitted color module
  137.  
  138.  This is hairy and slow - bends ray around normal vector
  139.  by ratio of indicies of refraction.  line->flag=TRUE
  140.  if we are inside a piece of glass - this means glass must
  141.  have a simple structure.
  142.  
  143.  10 Aug 88 - Fixed TransColor so that it works.  The
  144.  original algorithm came from a book, and I had some
  145.  problems getting it to work.  This one came from my head,
  146.  and seems to work ok.
  147.  
  148.  11 Aug 88 - Added density effects (light is reduced
  149.  more by thicker glass).
  150.  
  151.  **********************************************************/
  152.  
  153. /* #define TESTTRANS TRUE */
  154.  
  155. TransColor(color,cinfo,norm,loc,line,inmult)
  156.   SVECT_PTR color;
  157.   VECT_PTR norm,loc;
  158.   OBJ_PTR line;
  159.   CINFO_PTR cinfo;
  160.   float inmult;
  161. {
  162.   OBJ_STRUCT newline;
  163.   SVECTOR    col1;
  164.   VECTOR     toadd, negvect1, distance;
  165.   float      index2, multiplier, side1;
  166.   int        maxtrans;
  167.  
  168.   /* these vars are used to keep track of the distance
  169.      traveled through the glass so we can attenuate the
  170.      light accordingly.                                 */
  171.  
  172.   static     VECTOR prevpos;
  173.   VECTOR     displacement;
  174.   SVECTOR    attenuation;
  175.   float      glassdist;
  176.  
  177. # ifdef TRANSDEBUG
  178.     printf("TRANSCOLOR:\n");
  179. # endif
  180. # ifdef RAYDEBUG
  181.     printf("TRANSCOLOR:\n");
  182. # endif
  183.  
  184.   if ((cinfo->trans.r < def.ithreshold) &&
  185.       (cinfo->trans.g < def.ithreshold) &&
  186.       (cinfo->trans.b < def.ithreshold)) return;
  187.  
  188. # ifdef ROBUST
  189.     if (line->type!=LINE) Error(INTERNAL_ERROR,602);
  190.     if ((THEWORLD.globindex == 0) ||
  191.         (cinfo->index == 0))
  192.           Error(ZERO_INDEX,603);
  193. # endif
  194.  
  195.   if (line->flag) {
  196.  
  197.     /* inside an object going out ? */
  198.     index2 = cinfo->index/THEWORLD.globindex;
  199.  
  200.     /* find offset from prev position */
  201.     VecSubtract(&displacement,loc,&prevpos);
  202.  
  203.     /* measure distance */
  204.     glassdist = sqrt(DotProd(displacement,displacement));
  205.  
  206.   } else {
  207.  
  208.     /* outside an object going in ? */
  209.     index2 = THEWORLD.globindex/cinfo->index;
  210.     /* remember this position */
  211.     VectEQ(&prevpos,loc);
  212.   }
  213.  
  214.   /* doesn't currently use new_line() call */
  215.   newline.type = LINE;
  216.   newline.child = newline.nextobj = NULL;
  217.  
  218.   /* this ray starts from where we hit glass */
  219.   VectEQ(&(newline.loc),loc);
  220.   VectEqZero(&toadd);
  221.  
  222.   VectNegate(&negvect1,&(line->vect1));
  223.   side1 = DotProd((*norm),negvect1);
  224.  
  225.   VectAddMult(&toadd,-side1,norm,(float)1,&negvect1);
  226.  
  227.   VectScale(&toadd,(1-index2));
  228.  
  229.   VectorAdd(&(newline.vect1),&(line->vect1),&toadd);
  230.  
  231.   Normalize(&(newline.vect1));
  232.  
  233.   maxtrans = MAX(MAX(cinfo->trans.r,cinfo->trans.g),
  234.                      cinfo->trans.b);
  235.  
  236.   /* if we were inside, now we're out */
  237.   newline.flag = !(line->flag);
  238.  
  239. # ifdef TESTTRANS
  240.  
  241.     if (line->flag) printf("line TRUE\n");
  242.     if (newline.flag) printf("newline TRUE\n");
  243.  
  244.     printf("Trans = %d %d %d\n",cinfo->trans.r,
  245.                                 cinfo->trans.g,
  246.                                 cinfo->trans.b);
  247.  
  248.     printf("index2 = %f\n",index2);
  249.     printf("side1  = %f\n",side1);
  250.  
  251.     printf("Dot(toadd,norm) = %f\n",
  252.            DotProd(toadd,(*norm)));
  253.  
  254.     printf("Dot(norm,negvect1) = %f\n",
  255.            DotProd((*norm),negvect1));
  256.  
  257.     printf("Dot(-norm,newvect) = %f\n",
  258.            -DotProd((*norm),newline.vect1));
  259.  
  260.     printf("inmult, maxtrans = %f %d\n",inmult,maxtrans);
  261. # endif
  262.  
  263.   multiplier = inmult * (float)maxtrans/(float)CNUM;
  264.   Ray_Trace(&newline,&col1,multiplier);
  265.   THEWORLD.refl_trans++;
  266.  
  267. # ifdef TESTTRANS
  268.     printf("Col1 = %d %d %d\n",col1.r,col1.g,col1.b);
  269. # endif
  270.  
  271.   color->r += col1.r;
  272.  
  273.   color->g += col1.g;
  274.  
  275.   color->b += col1.b;
  276.  
  277.   if (line->flag) {          /* density effects? */
  278.  
  279.     /* density uses x,y,z not r,g,b cuz its a floating
  280.        point vector.                                   */
  281.  
  282.     attenuation.r = (int)(cinfo->density.x * glassdist *
  283.                          (float)(color->r));
  284.  
  285.     attenuation.g = (int)(cinfo->density.y * glassdist *
  286.                          (float)(color->g));
  287.  
  288.     attenuation.b = (int)(cinfo->density.z * glassdist *
  289.                          (float)(color->b));
  290.  
  291.     /* don't remove more than original intensity! */
  292.  
  293.     color->r -= MIN(attenuation.r,color->r);
  294.     color->g -= MIN(attenuation.g,color->g);
  295.     color->b -= MIN(attenuation.b,color->b);
  296.  
  297.   }
  298. }
  299.  
  300.  
  301. /**********************************************************
  302.  
  303.                    Reflective color module
  304.  
  305.       Bounce ray off object and recursively ray trace.
  306.  
  307.  **********************************************************/
  308.  
  309. ReflectColor(color,cinfo,norm,loc,line,inmult)
  310.   SVECT_PTR color;
  311.   VECT_PTR  norm,loc;
  312.   OBJ_PTR   line;
  313.   CINFO_PTR cinfo;
  314.   float inmult;
  315. {
  316.   SVECTOR col1;
  317.   OBJ_STRUCT newline;
  318.   float multiplier;
  319.   int maxmirror;
  320.  
  321. # ifdef ROBUST
  322.     if (line->type!=LINE) Error(INTERNAL_